﻿using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Text;

namespace TeaCompiler.CodeDom {

    #region Expression

    /// <summary>
    /// 表示一个表达式。
    /// </summary>
    public abstract class Expression : Node {

        //public virtual Type Type {
        //    get {
        //        return Type.Unknown;
        //    }
        //}

        ///// <summary>
        ///// 将当前节点写入指定的 IndentedTextWriter 。
        ///// </summary>
        ///// <param name="writer">写入工具。</param>
        //public override void Write(IndentedTextWriter writer) {
        //    //writer.Write(ToString());
        //}

        //public override void GenerateC(IndentedTextWriter writer) {

        //}
    }

    /// <summary>
    /// 表示一个标识符。
    /// </summary>
    public class Identifier : Expression {

        public string Name {
            get;
            set;
        }

        public override void Write(IndentedTextWriter writer) {
            writer.Write(Name);
        }

        public override string ToString() {
            return Name;
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitIdentifier(this);
        //}

        //#region ILiteral 成员


        ///// <summary>
        ///// 获取当前文本真正的字符串值。
        ///// </summary>
        ///// <value></value>
        //public string Value {
        //    get {
        //        return Name;
        //    }
        //}

        //#endregion

        //public override void GenerateC(IndentedTextWriter writer) {
        //    writer.Write(Name);
        //}
    }

    /// <summary>
    /// 表示一个条件表达式。
    /// </summary>
    public class ConditionalExpression : Expression {

        /// <summary>
        /// 获取条件。
        /// </summary>
        public Expression Condition {
            get;
            set;
        }

        /// <summary>
        /// 获取则语句。
        /// </summary>
        public Expression ThenExpression {
            get;
            set;
        }

        /// <summary>
        /// 获取否则语句。
        /// </summary>
        public Expression ElseExpression {
            get;
            set;
        }

        public override Location StartLocation {
            get {
                return Condition.StartLocation;
            }
            set {
                Condition.StartLocation = value;
            }
        }

        public override Location EndLocation {
            get {
                return ElseExpression.EndLocation;
            }
            set {
                ElseExpression.EndLocation = value;
            }
        }

        public override void Write(IndentedTextWriter writer) {
            Condition.Write(writer);
            writer.Write(' ');
            writer.Write('?');
            writer.Write(' ');
            ThenExpression.Write(writer);
            writer.Write(' ');
            writer.Write(':');
            writer.Write(' ');
            ElseExpression.Write(writer);
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitConditionalExpression(this);
        //}
    }

    /// <summary>
    /// 表示用括号括起来的表达式。
    /// </summary>
    public class ParenthesizedExpression : Expression {

        public Expression Expression {
            get;
            set;
        }

        public override void Write(IndentedTextWriter writer) {
            writer.Write('(');
            Expression.Write(writer);
            writer.Write(')');
        }

        //public override string ToString() {
        //    return String.Format("({0})", Expression);
        //}

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitParamedExpression(this);
        //}
    }

    #endregion

    #region UnaryExpression

    /// <summary>
    /// 表示一个单目运算表达式。
    /// </summary>
    public class UnaryExpression : Expression {

        /// <summary>
        /// 获取当前表达式的操作符。
        /// </summary>
        public TokenType Operator {
            get;
            set;
        }

        /// <summary>
        /// 获取表达式。
        /// </summary>
        public Expression Expression {
            get;
            set;
        }

        public override Location EndLocation {
            get {
                return Expression.EndLocation;
            }
            set {
                Expression.EndLocation = value;
            }
        }

        public override void Write(IndentedTextWriter writer) {
            writer.Write(Operator.GetName());
            switch (Operator) {
                case TokenType.New:
                case TokenType.Typeof:
                case TokenType.Await:
                case TokenType.Trace:
                case TokenType.Assert:
                case TokenType.Delete:
                    writer.Write(' ');
                    break;
            }

            Expression.Write(writer);
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitUnaryExpression(this);
        //}
    }

    /// <summary>
    /// 表示一个 trace 表达式。
    /// </summary>
    public class TraceExpression : UnaryExpression {

        /// <summary>
        /// 初始化 <see cref="TeaCompiler.CodeDom.TraceExpression"/>  的新实例。
        /// </summary>
        public TraceExpression() {
            Operator = TokenType.Trace;
        }

    }

    /// <summary>
    /// 表示一个 assert 表达式。
    /// </summary>
    public class AssertExpression : UnaryExpression {

        public Expression Throws {
            get;
            set;
        }

        /// <summary>
        /// 初始化 <see cref="TeaCompiler.CodeDom.AssertExpression"/>  的新实例。
        /// </summary>
        public AssertExpression() {
            Operator = TokenType.Assert;
        }

    }

    /// <summary>
    /// 表示一个后缀表达式计算表达式。
    /// </summary>
    public class PostfixExpression : UnaryExpression {

        public override Location StartLocation {
            get {
                return Expression.StartLocation;
            }
            set {
                Expression.StartLocation = value;
            }
        }

        /// <summary>
        /// 获取结束位置。
        /// </summary>
        /// <value></value>
        public override Location EndLocation {
            get;
            set;
        }

        public override void Write(IndentedTextWriter writer) {
            Expression.Write(writer);
            writer.Write(Operator.GetName());
        }

        ///// <summary>
        ///// 返回表示当前 <see cref="T:System.Object"/> 的 <see cref="T:System.String"/>。
        ///// </summary>
        ///// <returns>
        ///// 	<see cref="T:System.String"/>，表示当前的 <see cref="T:System.Object"/>。
        ///// </returns>
        //public override string ToString() {
        //    return Expression.ToString() + (Operator == TokenType.Inc ? "++" : "--");
        //}

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitPostfixExpression(this);
        //}
    }

    #endregion

    #region BinaryExpression

    /// <summary>
    /// 表示一个二目运算表达式。
    /// </summary>
    public class BinaryExpression : Expression {

        /// <summary>
        /// 获取左式。
        /// </summary>
        public Expression Left {
            get;
            set;
        }

        /// <summary>
        /// 获取当前表达式的操作符。
        /// </summary>
        public TokenType Operator {
            get;
            set;
        }

        /// <summary>
        /// 获取右式。
        /// </summary>
        public Expression Right {
            get;
            set;
        }

        public override Location StartLocation {
            get {
                return Left.StartLocation;
            }
            set {
                Left.StartLocation = value;
            }
        }

        public override Location EndLocation {
            get {
                return Right.EndLocation;
            }
            set {
                Right.EndLocation = value;
            }
        }

        public override void Write(IndentedTextWriter writer) {
            Left.Write(writer);
            writer.Write(' ');
            writer.Write(Operator.GetName());
            writer.Write(' ');
            Right.Write(writer);
        }

    }

    /// <summary>
    /// 表示类型定义表达式。
    /// </summary>
    public class TypeExpression : BinaryExpression {

        public override Location StartLocation {
            get;
            set;
        }

        public override void Write(IndentedTextWriter writer) {
            Left.Write(writer);
            switch (Operator) {
                case TokenType.LBrack:
                    writer.Write('[');
                    if (Right != null)
                        Right.Write(writer);
                    writer.Write(']');
                    break;
                case TokenType.Lt:
                    writer.Write('<');
                    if (Right != null)
                        Right.Write(writer);
                    writer.Write('>');
                    break;
                default:
                    writer.Write(Operator.GetName());
                    if (Right != null)
                        Right.Write(writer);
                    break;
            }
        }

    }

    /// <summary>
    /// 表示一个赋值语句。
    /// </summary>
    public class AssignmentExpression : BinaryExpression {

    }

    /// <summary>
    /// 表示一个类型转换表达式。
    /// </summary>
    public class CastExpression : BinaryExpression {

        public override Location StartLocation {
            get;
            set;
        }

        public override void Write(IndentedTextWriter writer) {
            if (Operator == TokenType.LParam) {
                writer.Write('(');
                Left.Write(writer);
                writer.Write(')');
                Right.Write(writer);
            } else {
                base.Write(writer);
            }

        }

    }

    #endregion

    #region CallExpression

    /// <summary>
    /// 表示一个Call语句。
    /// </summary>
    public abstract class CallExpression : Expression {

        /// <summary>
        /// 获取目标。
        /// </summary>
        public Expression Target {
            get;
            set;
        }

        /// <summary>
        /// 获取结束位置。
        /// </summary>
        /// <value></value>
        public override Location StartLocation {
            get {
                return Target.StartLocation;
            }
            set {
                Target.StartLocation = value;
            }
        }
    }

    /// <summary>
    /// 表示通过函数形式的调用。
    /// </summary>
    public class FunctionCallExpression : CallExpression {

        public class Argument : Node {

            public string Name {
                get;
                set;
            }

            public bool ByRef {
                get;
                set;
            }

            public Expression Value {
                get;
                set;
            }

            public override Location EndLocation {
                get {
                    return Value.EndLocation;
                }
                set {
                    Value.EndLocation = value;
                }
            }

            public override void Write(IndentedTextWriter writer) {
                if (Name != null) {
                    writer.Write(Name);
                    writer.Write(':');
                    writer.Write(' ');
                }

                if (ByRef) {
                    writer.Write("ref");
                }

                Value.Write(writer);
            }

        }

        public List<Argument> Arguments {
            get;
            set;
        }

        /// <summary>
        /// 将当前节点写入指定的 IndentedTextWriter 。
        /// </summary>
        /// <param name="writer">写入工具。</param>
        public override void Write(IndentedTextWriter writer) {
            Target.Write(writer);

            writer.Write('(');
            bool appendComma = false;
            foreach (Argument args in Arguments) {
                if (appendComma) {
                    writer.Write(',');
                    writer.Write(' ');
                } else {
                    appendComma = true;
                }
                args.Write(writer);
            }
            writer.Write(')');

        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitFunctionCallExpression(this);
        //}
    }

    /// <summary>
    /// 表示通过数组形式的调用。
    /// </summary>
    public class IndexCallExpression : CallExpression {

        public Expression Argument {
            get;
            set;
        }

        /// <summary>
        /// 将当前节点写入指定的 IndentedTextWriter 。
        /// </summary>
        /// <param name="writer">写入工具。</param>
        public override void Write(IndentedTextWriter writer) {
            Target.Write(writer);
            writer.Write('[');
            Argument.Write(writer);
            writer.Write(']');
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitIndexCallExpression(this);
        //}
    }

    /// <summary>
    /// 表示通过.形式的调用。
    /// </summary>
    public class PropertyCallExpression : IndexCallExpression {

        /// <summary>
        /// 将当前节点写入指定的 IndentedTextWriter 。
        /// </summary>
        /// <param name="writer">写入工具。</param>
        public override void Write(IndentedTextWriter writer) {
            Target.Write(writer);
            writer.Write('.');
            Argument.Write(writer);
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitPropertyCallExpression(this);
        //}
    }

    /// <summary>
    /// 表示通过.形式的调用。
    /// </summary>
    public class ChainCallExpression : PropertyCallExpression {

        /// <summary>
        /// 将当前节点写入指定的 IndentedTextWriter 。
        /// </summary>
        /// <param name="writer">写入工具。</param>
        public override void Write(IndentedTextWriter writer) {
            Target.Write(writer);
            writer.Write('.');
            writer.Write('.');
            Argument.Write(writer);
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitPropertyCallExpression(this);
        //}
    }

    /// <summary>
    /// 表示一个New语句。
    /// </summary>
    public class NewExpression : FunctionCallExpression {

        /// <summary>
        /// 获取结束位置。
        /// </summary>
        /// <value></value>
        public override Location StartLocation {
            get;
            set;
        }

        public override void Write(IndentedTextWriter writer) {
            writer.Write("new ");

            if (Arguments == null) {
                Target.Write(writer);
            } else {
                base.Write(writer);
            }
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitNewExpression(this);
        //}
    }

    /// <summary>
    /// 表示一个New语句。
    /// </summary>
    public class NewArrayExpression : NewExpression {

        public override void Write(IndentedTextWriter writer) {
            writer.Write("new ");
            Target.Write(writer);
            writer.Write('[');
            Arguments[0].Value.Write(writer);
        }

        //[System.Diagnostics.DebuggerStepThrough]
        //public override void Accept(IAstVisitor visitor) {
        //    visitor.VisitNewExpression(this);
        //}
    }

    #endregion

}
